home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
xlisp.lbr
/
XLREAD.CQ
/
xlread.c
Wrap
Text File
|
1985-06-03
|
13KB
|
461 lines
/* xlread - xlisp expression input routine */
#ifdef CI_86
#include "a:stdio.h"
#include "xlisp.h"
#endif
#ifdef AZTEC
#include "a:stdio.h"
#include "xlisp.h"
#endif
#ifdef unix
#include <stdio.h>
#include <ctype.h>
#include <xlisp.h>
#endif
/* global variables */
struct node *oblist;
/* external variables */
extern struct node *xlstack;
extern int (*xlgetc)();
extern int xlplevel;
/* local variables */
static int savech;
/* forward declarations (the extern hack is for decusc) */
extern struct node *parse();
extern struct node *plist();
extern struct node *pstring();
extern struct node *pnumber();
extern struct node *pquote();
extern struct node *pname();
#ifdef REALS
extern struct node *pfloat();
#endif
/**************************************
* xlread - read an xlisp expression *
**************************************/
struct node *xlread()
{
savech = -1; /* initialize */
xlplevel = 0;
return (parse()); /* Parse an expression */
}
/**************************************
* parse - parse an xlisp expression *
**************************************/
static struct node *parse()
{
int ch;
while (TRUE) /* Look for a node, skipp comments */
{
switch (ch = nextch()) /* Switch on next character */
{
case '\'': /* a quoted expression */
return (pquote());
case '(': /* a sublist */
return (plist());
case ')': /* closing paren - shouldn't happen */
xlfail("extra right paren");
case '.':
#ifdef REALS
return (pfloat(0)); /* Real fractional only */
#else
xlfail("misplaced dot");/* dot - shouldn't happen */
#endif
case ';': /* a comment */
pcomment();
break;
case '"': /* a string */
return (pstring());
default:
if (isdigit(ch)) /* a number */
return (pnumber(1));
else if (issym(ch)) /* a name */
return (pname());
else
xlfail("invalid character");
}
}
}
/*******************************
* pcomment - parse a comment *
*******************************/
static pcomment()
{
while (getch() != '\n') /* Skip to end of line */
;
}
/*************************
* plist - parse a list *
*************************/
static struct node *plist()
{
struct node *oldstk,val,*lastnptr,*nptr;
int ch;
xlplevel += 1; /* Increment nesting level */
oldstk = xlsave(&val,NULL); /* Create .... */
savech = -1; /* Skip opend paren */
/* keep appending nodes until a closing paren is found */
for (lastnptr = NULL; (ch = nextch()) > 0 && ch != ')'; lastnptr = nptr)
{
if (ch == '.') /* Check for a dotted pair */
{
savech = -1; /* Skip the dot */
if (lastnptr == NULL) /* Make sure there is a node */
xlfail("invalid dotted pair");
lastnptr->n_listnext = parse(); /* Parse expression */
if (nextch() != ')') /* Check for closing paren */
xlfail("invalid dotted pair");
break; /* Done with this list */
}
nptr = newnode(LIST); /* Allocate and link new node */
if (lastnptr == NULL)
val.n_ptr = nptr;
else
lastnptr->n_listnext = nptr;
nptr->n_listvalue = parse(); /* Initialize it */
}
savech = -1; /* Skip the closing paren */
xlstack = oldstk; /* Restore previous stack frame */
xlplevel -= 1; /* Decrement nesting level */
return (val.n_ptr); /* Successful return */
}
/*****************************
* pstring - parse a string *
*****************************/
static struct node *pstring()
{
struct node *oldstk,val;
char sbuf[STRMAX+1];
int ch,i,d1,d2,d3;
oldstk = xlsave(&val,NULL); /* Create a new stack frame */
savech = -1; /* Skip opening quote */
/* loop looking for a closing qte */
for (i = 0; i < STRMAX && (ch = getch()) != '"'; i++)
{
switch (ch)
{
case '\\':
switch (ch = getch())
{
case 'e':
ch = '\033';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
d1 = ch - '0';
while (((ch = getch()) >= '0') && (ch < '8'))
d1 = d1 <<3 + (ch - '0');
ch = d1;
break;
default:
break;
}
}
sbuf[i] = ch;
}
sbuf[i] = 0;
val.n_ptr = newnode(STR); /* Initialize the node */
val.n_ptr->n_str = strsave(sbuf);
xlstack = oldstk; /* Restore old stack frame */
return (val.n_ptr); /* .. and return */
}
#ifdef REALS
/********************************************************
* pfloat - parse the fractional part of a real number *
********************************************************/
static struct node *pfloat(i)
int i;
{
struct node *val;
int ch;
long float rval = (float) ((i<0) ? -i : i), fp= 1;
for ( ; isdigit(ch = thisch()); savech = -1)
rval = rval + (ch - '0')/(fp *= 10);
if (issym(ch)) /* ensure correct termination */
xlfail("badly formed number");
val = newnode(REAL); /* Initialze the new node */
val->n_real = (i < 0) ? -rval : rval;
return (val);
}
#endif
/*****************************
* pnumber - parse a number *
*****************************/
static struct node *pnumber(sign)
int sign;
{
struct node *val;
int ch,ival = 0;
for ( ; isdigit(ch = thisch()); savech = -1) /* loop while digits */
ival = ival * 10 + ch - '0';
#ifdef REALS
if (ch == '.')
{
savech = -1;
return pfloat(sign*ival);
}
#endif
if (issym(ch)) /* ensure correct termination */
xlfail("badly formed number");
val = newnode(INT); /* Initialze the new node */
val->n_int = sign * ival;
return (val);
}
/***************************************************
* xlenter - enter a symbol into the symbol table *
***************************************************/
struct node *xlenter(sname)
char *sname;
{
struct node *sptr;
if (strcmp(sname,"nil") == 0) /* Check for nil */
return (NULL);
if (oblist == NULL) /* Create oblist if required */
{
oblist = newnode(SYM);
oblist->n_symname = strsave("oblist");
oblist->n_symvalue = newnode(LIST);
oblist->n_symvalue->n_listvalue = oblist;
}
sptr = oblist->n_symvalue; /* check for symbol already in table */
while (sptr != NULL)
{
if (sptr->n_listvalue == NULL)
{
printf("bad oblist\n");
sptr = oblist->n_symvalue;
while (sptr != NULL)
{
if (sptr->n_listvalue == NULL)
xlfail("end oblist");
printf("\n%s",sptr->n_listvalue->n_symname);
sptr = sptr->n_listnext;
}
}
else if (sptr->n_listvalue->n_symname == NULL)
printf("bad oblist symbol\n");
else
if (strcmp(sptr->n_listvalue->n_symname,sname) == 0)
return (sptr->n_listvalue);
sptr = sptr->n_listnext;
}
sptr = newnode(LIST); /* Create and link new symbol */
sptr->n_listnext = oblist->n_symvalue;
oblist->n_symvalue = sptr;
sptr->n_listvalue = newnode(SYM);
sptr->n_listvalue->n_symname = strsave(sname);
return (sptr->n_listvalue);
}
/***************************************
* pquote - parse a quoted expression *
***************************************/
static struct node *pquote()
{
struct node *oldstk,val;
oldstk = xlsave(&val,NULL); /* Create new stack frame */
savech = -1; /* Skip the quote character */
val.n_ptr = newnode(LIST); /* Allocate two new nodes */
val.n_ptr->n_listvalue = xlenter("quote");
val.n_ptr->n_listnext = newnode(LIST);
val.n_ptr->n_listnext->n_listvalue = parse();
xlstack = oldstk; /* Restore old stack frame */
return (val.n_ptr); /* .. return quoted expression */
}
/********************************
* pname - parse a symbol name *
********************************/
static struct node *pname()
{
char sname[STRMAX+1];
int ch,i;
ch = sname[0] = getch(); /* Get first character */
if (ch == '+' || ch == '-') /* Check for signed number */
{
if (isdigit(thisch()))
return (pnumber(ch == '+' ? 1 : -1));
}
for (i = 1; i < STRMAX && issym(thisch()); i++) /* get symbol name */
sname[i] = getch();
sname[i] = 0;
return (xlenter(sname)); /* Initialize value */
}
/**************************************************
* nextch - look at the next non-blank character *
**************************************************/
static int nextch()
{
while (isspace(thisch())) /* Find non blank character */
savech = -1;
return savech; /* .. and return it */
}
/*******************************************
* thisch - look at the current character *
*******************************************/
static int thisch()
{
return (savech = getch()); /* return and save next character */
}
/***********************************
* getch - get the next character *
***********************************/
static int getch()
{
int ch;
if ((ch = savech) >= 0) /* Check for saved character */
savech = -1;
else
ch = (*xlgetc)();
if (ch == EOF) /* Check for abort character */
if (xlplevel > 0)
{
putchar('\n');
xltin(FALSE);
xlfail("input aborted");
}
else
exit();
return (ch); /* Return char */
}
/****************************************************************
* issym - check whether a character if valid in a symbol name *
****************************************************************/
static int issym(ch)
int ch;
{
if (isspace(ch))
return FALSE;
switch (ch)
{
case ' ':
case '(':
case ')':
case ';':
case '.':
case '"':
case '\\':
return (FALSE);
default:
return (TRUE);
}
}